#include <vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "uPrmMail.h"
#include <ShareMem.hpp>
#include <Registry.hpp>
#include <stdio.h>
#include "CInet.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
//---------------------------------------------------------------------------
#define MODULE_TAG 4554
//---------------------------------------------------------------------------
#define MAX_SAVE_EMAIL_ADR 10
//---------------------------------------------------------------------------
char *SECTION_PARAM_EMAIL   = "EMail";
#define SMTPDESTEMAILADDRESS "SMTPDestEmailAddress"
//---------------------------------------------------------------------------
#define ACCOUNT_NAME                          "Account Name"
#define POP3_SERVER                           "POP3 Server"
#define SMTP_SERVER                           "SMTP Server"
#define POP3_USER_NAME                        "POP3 User Name"
#define SMTP_EMAIL_ADDRESS                    "SMTP Email Address"
//---------------------------------------------------------------------------
#define MAX_PASSWORD_LEN       32
//---------------------------------------------------------------------------
PACKAGE_OUTILS bool EnvoyerMail( AnsiString &strDestAddress, const AnsiString &strObject, const AnsiString &strText, const AnsiString &strFileName,const AnsiString &EMailTechnique,const AnsiString &strFichierIni, int Options)
{
  TfrmParamMail *frmParamMail = NULL;
  int            nModalResult = mrCancel;
  try {
    frmParamMail   = new TfrmParamMail( false, strDestAddress, strObject, strText, strFileName,EMailTechnique,strFichierIni, Options);
    if (Options & OM_SANS_FENETRE)
      {
        ASSERT(!strDestAddress.IsEmpty());         //Tout doit être renseigné à l'avance
        ASSERT(!strObject.IsEmpty());
        ASSERT(!strText.IsEmpty());

        if (frmParamMail->gbParamCpt->Visible)
          {//Le compte n'est pas paramétré
            delete frmParamMail;
            if (ParametrerMail())                  //On paramètre
              return EnvoyerMail(strDestAddress,strObject,strText,strFileName,EMailTechnique,strFichierIni,Options); //On envoie le message
            else
              return false;                        //On arrête tout
          }
        else
          {
            frmParamMail->btnValider->Click();
            nModalResult = mrOk;
          }
      }
    else
      nModalResult   = frmParamMail->ShowModal();
    strDestAddress = frmParamMail->cbAdrDest->Text;
  } catch( Exception &e) {
    ::EICDisplayException( TAG( 5), e);
  }
  delete frmParamMail;
  return ( nModalResult==mrOk);
}
//---------------------------------------------------------------------------
PACKAGE_OUTILS bool ParametrerMail()
{
  TfrmParamMail *frmParamMail = NULL;
  int            nModalResult = mrCancel;
  try {
    frmParamMail   = new TfrmParamMail( true, EmptyStr, EmptyStr, EmptyStr, EmptyStr,EmptyStr, EmptyStr);
    nModalResult   = frmParamMail->ShowModal();
  } catch( Exception &e) {
    ::EICDisplayException( TAG( 6), e);
  }
  delete frmParamMail;
  return ( nModalResult==mrOk);
}
//---------------------------------------------------------------------------
PACKAGE_OUTILS bool RecupererParametrageMail( EMAIL_TRANSFERT eType, AnsiString &strPop, AnsiString &strSmtp, AnsiString &strCompte, AnsiString &strPassword, AnsiString &strAdrMail, AnsiString &strPortPOP,AnsiString &strPortSMTP )
{
  TfrmParamMail *frmParamMail = NULL;
  bool           bReturn      = false;
  try {
    frmParamMail   = new TfrmParamMail( true, EmptyStr, EmptyStr, EmptyStr, EmptyStr,EmptyStr,EmptyStr);
    strPop         = frmParamMail->edSvrPOP   ->Text;
    strSmtp        = frmParamMail->edSvrSMTP  ->Text;
    strPortPOP     = frmParamMail->edPortPOP  ->Text.Trim().IsEmpty() ? AnsiString("110") : frmParamMail->edPortPOP->Text;
    strPortSMTP    = frmParamMail->edPortSMTP ->Text.Trim().IsEmpty() ? AnsiString("25") : frmParamMail->edPortSMTP->Text;;
    strCompte      = frmParamMail->edNomCompte->Text;
    strPassword    = frmParamMail->edPassword ->Text;
    strAdrMail     = frmParamMail->edAdrEmail ->Text;
  } catch( Exception &e) {
    ::EICDisplayException( TAG( 7), e);
  }

  bReturn = frmParamMail->ParametrageEMailOk( eType);

  delete frmParamMail;
  return bReturn;
}
//---------------------------------------------------------------------------
__fastcall TfrmParamMail::TfrmParamMail( bool bParam, const AnsiString &strDestAddress, const AnsiString &strObject, const AnsiString &strText, const AnsiString &strFileName,const AnsiString &EMailTechnique,const AnsiString &strFichierIni, int Options, TComponent* Owner)
  : CForm(Owner /* = NULL */)
{
  char szBuffer[MAX_PASSWORD_LEN];
  bool       bResult   = true;
  bool       bOutlook  = false;
  TRegistry *pRegistry = NULL;
  TStrings  *pKeys     = new TStringList();
  AnsiString strKey( "Software\\Microsoft\\Internet Account Manager\\Accounts");

  if (!bParam)
    Caption = "Envoi de message électronique";
  m_strPieceJointe = strFileName;
  m_strFichierIni = strFichierIni;
  m_bParametrage   = bParam;
  m_Options = Options;
  if (!strDestAddress.IsEmpty())
    {
      cbAdrDest->Items->Add(strDestAddress);
      cbAdrDest->ItemIndex = 0;
    }
  if (cbAdrDest->Items->IndexOf(EMailTechnique) == -1)
    cbAdrDest->Items->Add(EMailTechnique);//On rajoute l'email technique en début de liste
   edObject->Text  = strObject;
    memBody->Text  = strText;

  // Recherche tous les comptes mail disponibles dans Outlook Express
  pRegistry = new TRegistry();
   ASSERT( pRegistry->RootKey==HKEY_CURRENT_USER);
lblRetry:
  if( pRegistry->OpenKey( strKey, false)) {
      pRegistry->GetKeyNames( pKeys);
      pRegistry->CloseKey();
    for( int i=pKeys->Count-1; i>=0; i--) {
      if(( bResult=pRegistry->OpenKey( strKey + "\\" + pKeys->Strings[i], false))==true) {
        try         { bResult = !pRegistry->ReadString( SMTP_EMAIL_ADDRESS).IsEmpty(); }
        catch( ...) { bResult = false; }
        pRegistry->CloseKey();
      }
      if( !bResult) pKeys->Delete( i);
    }
  }

  if(( pKeys->Count==0) && !bOutlook) {
    bOutlook = true; // On va vérifier les comptes disponibles dans Outlook d'Office
    strKey = "Software\\Microsoft\\Office\\Outlook\\OMI Account Manager\\Accounts";
    goto lblRetry;
  }

  // Récupère les informations de tous les comptes
  m_pMails = new TParamMail[pKeys->Count];
  for( int i=0; i<pKeys->Count; i++) {
    if( pRegistry->OpenKey( strKey + "\\" + pKeys->Strings[i], false)) {
      m_pMails[i].strName                             = pRegistry->ReadString( ACCOUNT_NAME                        );
      m_pMails[i].strPop                              = pRegistry->ReadString( POP3_SERVER                         );
      m_pMails[i].strSmtp                             = pRegistry->ReadString( SMTP_SERVER                         );
      m_pMails[i].strUsrName                          = pRegistry->ReadString( POP3_USER_NAME                      );
      m_pMails[i].strAddress                          = pRegistry->ReadString( SMTP_EMAIL_ADDRESS                  );
      pRegistry->CloseKey();
    }
  }

  // Affichage de la liste des comptes
  AfficherParamCompteMail();
  if( !pRegistry->KeyExists("Software\\EIC\\EMAIL"/*\\POP3Server"*/) && ( pKeys->Count>=1)) {
    // Les paramétrages de la boite aux lettres ne sont pas renseignés, on va proposer
    // à l'utilisateur de lui récupérer ceux d'Outlook
    if( EICQuestion( "Les paramètres de votre boite aux lettres ne sont pas renseignés.\nVoulez-vous que le logiciel essaye de récupérer les paramètres de votre messagerie ?", "Question")) {
      int nIndex  = 0;
      if(( pKeys->Count==1) ||
        (( pKeys->Count> 1) && (( nIndex=ChoisirCompteMail( m_pMails, pKeys->Count))>=0))) {
        edSvrPOP   ->Text = m_pMails[nIndex].strPop;
        edSvrSMTP  ->Text = m_pMails[nIndex].strSmtp;
        edNomCompte->Text = m_pMails[nIndex].strUsrName;
        edAdrEmail ->Text = m_pMails[nIndex].strAddress;
      }
    }
  }

         pKeys->Clear();
  delete pKeys;
  delete pRegistry;

  if( m_bParametrage) {
    btnValider->Caption = "&Valider";
    gbAdrDest ->Visible = false;
  }
  gbBody->Visible  = Options & OM_CAN_MODIFY_BODY;

  ResizeWindow();
}
//---------------------------------------------------------------------------
__fastcall TfrmParamMail::~TfrmParamMail()
{
  delete []m_pMails;
}
//---------------------------------------------------------------------------
void __fastcall TfrmParamMail::AfficherParamCompteMail( bool bUseParam /* = true */)
{
  char szBuffer[MAX_PASSWORD_LEN];
  int Position;
  AnsiString Adresse,strAdr;
  TRegistry *pRegistry = NULL;
  pRegistry = new TRegistry();
  if (pRegistry->OpenKey("Software\\EIC\\EMAIL", false))
  {
    edSvrPOP     ->Text = pRegistry->ReadString("POP3Server");
    if (pRegistry->ValueExists("POP3Port"))
      edPortPOP->Text = pRegistry->ReadString("POP3Port");
    else
      edPortPOP->Text = "110";
    edSvrSMTP    ->Text = pRegistry->ReadString("SMTPServer");
    if (pRegistry->ValueExists("SMTPPort"))
      edPortSMTP->Text = pRegistry->ReadString("SMTPPort");
    else
      edPortSMTP->Text = "25";
    edNomCompte  ->Text = pRegistry->ReadString("POP3UserName");
    if (pRegistry->ReadBinaryData("POP3Password",szBuffer,MAX_PASSWORD_LEN) != 0)
      edPassword   ->Text    = DecryptPassword( szBuffer);
    edAdrEmail   ->Text = pRegistry->ReadString("SMTPEmailAddress");
  }
  TIniFile *pIniFile = new TIniFile(m_strFichierIni);
  // Créer la liste des adresses destinataires
  for( int i=0; i<MAX_SAVE_EMAIL_ADR; i++) {
    strAdr = pIniFile->ReadString( SECTION_PARAM_EMAIL, SMTPDESTEMAILADDRESS + IntToStr( i+1), EmptyStr);
    if( !strAdr.IsEmpty() && (cbAdrDest->Items->IndexOf(strAdr) == -1))
      cbAdrDest->Items->Add( strAdr);
  }
  // On fait passer la dernière adresse utilisée en premier, sans la sélectionner
  Adresse = pIniFile->ReadString( SECTION_PARAM_EMAIL, SMTPDESTEMAILADDRESS, EmptyStr);
  if (!Adresse.IsEmpty() && !(m_Options & OM_SANS_FENETRE))
    {
      Position = cbAdrDest->Items->IndexOf(Adresse);
      if (Position == -1)
        cbAdrDest->Items->Insert(0,Adresse);
      else
        cbAdrDest->Items->Move(Position,0);
    }
  delete pIniFile;
  delete pRegistry;
  if( !m_bParametrage) gbParamCpt->Visible = !ParametrageEMailOk( ET_SEND);
  btnParam->Visible = !m_bParametrage && !gbParamCpt->Visible;
}
//---------------------------------------------------------------------------
void __fastcall TfrmParamMail::btnValiderClick(TObject *Sender)
{
  char szBuffer[MAX_PASSWORD_LEN];
  AnsiString Body;
  TRegistry *pRegistry = NULL;
  pRegistry = new TRegistry();
  pRegistry->OpenKey("Software\\EIC\\EMAIL", true);
  pRegistry->WriteString("POP3Server",edSvrPOP->Text);
  pRegistry->WriteString("POP3Port",edPortPOP->Text);
  pRegistry->WriteString("SMTPServer",edSvrSMTP->Text);
  pRegistry->WriteString("SMTPPort",edPortSMTP->Text);
  pRegistry->WriteString("POP3UserName",edNomCompte->Text);
  pRegistry->WriteString("SMTPEmailAddress",edAdrEmail->Text);
  EncryptPassword( edPassword->Text, szBuffer);
  pRegistry->WriteBinaryData("POP3Password",szBuffer,MAX_PASSWORD_LEN);

  if (gbAdrDest->Visible && (m_Options & OM_NOM_DESTINATAIRE_OBLIGATOIRE) && eDestinataire->Text.IsEmpty())
    {
      EICInformation("Le nom du destinataire n'est pas saisi.");
      eDestinataire->SetFocus();
      return;
    }
  if (gbAdrDest->Visible && eDestinataire->Text.Pos("@"))
    {
      EICInformation("Vous avez saisi le caractère '@' dans le nom du destinataire.\n"
                     "Attention de ne pas confondre le nom du destinataire (nom de la personne physique)\n"
                     "avec son adresse e-mail.");
      eDestinataire->SetFocus();
      return;
    }
  if (gbAdrDest->Visible && cbAdrDest->Text.IsEmpty())
    {
      EICInformation("L'adresse e-mail du destinataire n'est pas saisie.");
      cbAdrDest->SetFocus();
      return;
    }
  if (gbBody->Visible && (m_Options & OM_SAISIR_MOTIF) && memBody->Text.IsEmpty())
    {
      EICInformation("Veuillez compléter le motif de votre envoi.");
      memBody->SetFocus();
      return;
    }

  if( m_bParametrage)
    {
      ModalResult = mrOk;
      return;
    }

  // Sauvegarde de l'adresse de destination
  int        nPos;
  CInternet  InternetConnection;
  TIniFile  *pIniFile = new TIniFile(m_strFichierIni);

  if(( nPos=cbAdrDest->Items->IndexOf( cbAdrDest->Text))==-1)
       cbAdrDest->Items->Insert( 0, cbAdrDest->Text); // L'adresse n'a jamais été utilisé, on la rajoute dans la liste au début
  else cbAdrDest->Items->Move( nPos, 0);              // L'adresse a déjà été utilisé, on la déplace en tête de liste

  // On sauvegarde la liste des adresses
  int nAdrToSave = cbAdrDest->Items->Count>MAX_SAVE_EMAIL_ADR ? MAX_SAVE_EMAIL_ADR : cbAdrDest->Items->Count;
  for( int i=0; i<nAdrToSave; i++)
    pIniFile->WriteString( SECTION_PARAM_EMAIL, SMTPDESTEMAILADDRESS + IntToStr( i+1), cbAdrDest->Items->Strings[i]);

  // Sauvegarde de la dernière adresse utilisée
         pIniFile->WriteString( SECTION_PARAM_EMAIL, SMTPDESTEMAILADDRESS, cbAdrDest->Text);
  delete pIniFile;

  if( !ParametrageEMailOk( ET_SEND)) {
    ::EICAttention( "Vous n'avez pas saisi tous les paramètres de votre messagerie.");
    edSvrPOP->SetFocus();
    ModalResult = mrNone;
    Abort();
  }

  InternetConnection.Connect((TCustomForm*)this);

  m_eBarre.Titre = "@-mail";
  m_eBarre.Messages = "Connexion au serveur de messagerie\nEnvoi de l'e-mail";
  m_eBarre.Open();
  m_eBarre.Max = 2;

  // Prépare l'envoi du message
  try {
    smtpEnvoi->Username = edNomCompte->Text;
    smtpEnvoi->Password =  edPassword->Text;
    smtpEnvoi->Host     =   edSvrSMTP->Text;
    smtpEnvoi->Port     =  edPortSMTP->Text.Trim().IsEmpty() ? 25 :StrToInt(edPortSMTP->Text);
    smtpEnvoi->AuthenticationType = atLogin;
    smtpEnvoi->Connect( IdTimeoutDefault);

    m_eBarre.NextMessage();

    if( smtpEnvoi->Connected()) {
      m_bDisplayBarre = true;
      msgCurrent->Clear();
      msgCurrent->From->Text                 = edAdrEmail->Text;
      msgCurrent->Recipients->EMailAddresses =  cbAdrDest->Text;
      msgCurrent->Subject                    = edObject->Text;
      msgCurrent->Priority                   = mpNormal;
      if (!eDestinataire->Text.IsEmpty())
        Body = "Destinataire : " + eDestinataire->Text + "\n\n";
      msgCurrent->Body->Text                 = Body + memBody->Text;
      msgCurrent->ReceiptRecipient->Text     = EmptyStr;
      TStringList *ListePiecesJointes = new TStringList();
      ListePiecesJointes->CommaText = m_strPieceJointe;
      for (int i = 0;i < ListePiecesJointes->Count;i++)
        new TIdAttachment( msgCurrent->MessageParts, ListePiecesJointes->Strings[i]);
      delete ListePiecesJointes;
      smtpEnvoi->Send( msgCurrent); m_bDisplayBarre = false;
      smtpEnvoi->Disconnect();
      ModalResult = mrOk;
    } else {
      ::EICErreur( "Impossible de se connecter à votre serveur de messagerie.");
    }
    InternetConnection.Disconnect();
  } catch( EIdProtocolReplyError &e) {
    InternetConnection.Disconnect();
    EICErreur(e.Message);
  }
    catch( Exception &e) {
    InternetConnection.Disconnect();
    EICDisplayException(TAGL,e);
  }

  m_eBarre.Close();
}
//---------------------------------------------------------------------------
int __fastcall TfrmParamMail::GetTotalAttachFile()
{
  TIdAttachment *attachObj;
  FILE          *fHandle;
  int            nTotalSize = 0;

  for( int i=0; i<msgCurrent->MessageParts->Count; i++) {
    if(( attachObj=dynamic_cast< TIdAttachment*>( msgCurrent->MessageParts->Items[i]))==NULL) continue;
    if(( fHandle=fopen( attachObj->StoredPathName.c_str(), "rb"))!=NULL) {
      fseek( fHandle, 0, SEEK_END);
      nTotalSize += ( int)(( double)ftell( fHandle) * 1.40);
      fclose( fHandle);
    }
  }

  return nTotalSize;
}
//---------------------------------------------------------------------------
void __fastcall TfrmParamMail::smtpEnvoiWorkBegin(TObject *Sender,
      TWorkMode AWorkMode, const int AWorkCountMax)
{
  if(( AWorkMode==wmWrite) && m_bDisplayBarre)
    m_eBarre.Max = AWorkCountMax==0 ? GetTotalAttachFile() : AWorkCountMax;
}
//---------------------------------------------------------------------------
void __fastcall TfrmParamMail::smtpEnvoiWork(TObject *Sender,
      TWorkMode AWorkMode, const int AWorkCount)
{
  if(( AWorkMode==wmWrite) && m_bDisplayBarre) m_eBarre = AWorkCount;
}
//---------------------------------------------------------------------------
void __fastcall TfrmParamMail::btnParamClick(TObject *Sender)
{
  gbParamCpt->Visible = true;
    btnParam->Visible = false;
  ResizeWindow();
}
//---------------------------------------------------------------------------
bool __fastcall TfrmParamMail::ParametrageEMailOk( EMAIL_TRANSFERT eTransfert)
{
  bool bReturn = false;

  if( eTransfert==ET_RECEIVE)
    bReturn = ( !edSvrPOP  ->Text.IsEmpty() && !edNomCompte->Text.IsEmpty() &&
                !edPassword->Text.IsEmpty() && !edPortPOP->Text.Trim().IsEmpty());

  if( eTransfert==ET_SEND)
    bReturn = ( !edSvrSMTP ->Text.IsEmpty() && !edNomCompte->Text.IsEmpty() &&
                !edPassword->Text.IsEmpty() && !edAdrEmail ->Text.IsEmpty() &&
                !edPortSMTP->Text.Trim().IsEmpty());

  return bReturn;
}
//---------------------------------------------------------------------------
void __fastcall TfrmParamMail::ResizeWindow()
{
  // Recalcule la taille de la fenêtre
  int nHeight = 0;
  for( int i=0; i<ControlCount; i++) {
    TWinControl *pWndCtrl = dynamic_cast< TWinControl*>( Controls[i]);
    if( pWndCtrl && pWndCtrl->Visible) nHeight += pWndCtrl->Height;
  }
  ClientHeight = nHeight;
  // Force la fenêtre à ce repositionner
  FORM_POSITION efrmPos = EICPosition;
  EICPosition = ( FORM_POSITION)0;
  EICPosition = efrmPos;
}
//---------------------------------------------------------------------------



void __fastcall TfrmParamMail::edPortPOPKeyPress(TObject *Sender, char &Key)
{
  //On n'accepte que les chiffres
  if (Key < '0' || Key > '9')
    Key = '\0';
}
//---------------------------------------------------------------------------

